//  公共功能代码
const crypto = require('crypto')
const request = require('request-promise')
const CONFIG = require('./util.config')// 配置地址文件
const REDIS = require('./util.redis')
// const schedule = require('node-schedule')// 定时任务
// const async = require('async'); //事件控制
// const fs = require('fs')
// console.log(CONFIG)
const token = 'wallet'

// 获取授权的accesstoken
async function getWechatOpenid (req) {
  let body
  let url = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${CONFIG.appid}&secret=${CONFIG.appsecret}&code=${req.code}&grant_type=authorization_code`
  await request(url)
  .then(ret => {
    body = JSON.parse(ret)
    console.log('get openid from wechat server:', body)
    REDIS.setRedis('yezi_refresh_token', body.refresh_token, 2592000)
  })
  .catch(err => { console.error(err) })
  return body
}
// 获取用户信息
async function getWexinUserInfo (opts) {
  let body
  // console.log(opts.access_token)
  let url = `https://api.weixin.qq.com/sns/userinfo?access_token=${opts.access_token}&openid=${opts.openid}&s&lang=zh_CN`
  await request(url)
  .then(ret => {
    body = JSON.parse(ret)
    console.log('get user info from wechat:', body)
  })
  .catch(err => { console.error(err) })
  return body
}
// 解密calback
function decryptCallback (encrypt, msgSignature, timeStamp, nonce, callback) {
  var token = 'wallet'
  this.key = new Buffer('4eFnNBsWJ42PlU4Ur087swKsuIEsn2FduWODKGZo7aO' + '=', 'base64') // toString('binary');
  this.iv = this.key.slice(0, 16)

  var aesCipher = crypto.createDecipheriv('aes-256-cbc', this.key, this.iv)
  aesCipher.setAutoPadding(false)
  var decipheredBuff = Buffer.concat([aesCipher.update(encrypt, 'base64'), aesCipher.final()])
  decipheredBuff = this.PKCS7Decoder(decipheredBuff)
  var len_netOrder_corpid = decipheredBuff.slice(16)
  var msg_len = len_netOrder_corpid.slice(0, 4).readUInt32BE(0)
// recoverNetworkBytesOrder(len_netOrder_corpid.slice(0, 4));
  var result = len_netOrder_corpid.slice(4, msg_len + 4).toString()
  var appId = len_netOrder_corpid.slice(msg_len + 4).toString()
  if (appId != this.appID) throw new Error('appId is invalid')

  var msgType = this.getXMLNodeValue('MsgType', result)
  var tmp = msgType.split('[')
  msgType = tmp[2].split(']')

  switch (msgType[0]) {
    case 'text':
      var toUserName = this.getXMLNodeValue('ToUserName', result)
      var tmp = toUserName.split('[')
      toUserName = tmp[2].split(']')

      var fromUserName = this.getXMLNodeValue('FromUserName', result)
      var tmp = fromUserName.split('[')
      fromUserName = tmp[2].split(']')

      var createTime = this.getXMLNodeValue('CreateTime', result)

      var content = this.getXMLNodeValue('Content', result)
      var tmp = content.split('[')
      content = tmp[2].split(']')

      return {
        ToUserName: toUserName[0],
        FromUserName: fromUserName[0],
        CreateTime: createTime,
        MsgType: msgType[0],
        Content: content[0]
      }
      break
    case 'event':
      var toUserName = this.getXMLNodeValue('ToUserName', result)
      var tmp = toUserName.split('[')
      toUserName = tmp[2].split(']')

      var fromUserName = this.getXMLNodeValue('FromUserName', result)
      var tmp = fromUserName.split('[')
      fromUserName = tmp[2].split(']')

      var createTime = this.getXMLNodeValue('CreateTime', result)

      var event = this.getXMLNodeValue('Event', result)
      var tmp = event.split('[')
      event = tmp[2].split(']')

      var succTime = this.getXMLNodeValue('SuccTime', result)
      var tmp = succTime.split('[')
      succTime = tmp[2].split(']')

      if (!succTime[0]) {
        var reason = this.getXMLNodeValue('Reason', result)
        var tmp = reason.split('[')
        Reason = tmp[2].split(']')

        var failTime = this.getXMLNodeValue('FailTime', result)
        var tmp = failTime.split('[')
        failTime = tmp[2].split(']')

        return {
          ToUserName: toUserName[0],
          FromUserName: fromUserName[0],
          CreateTime: createTime,
          MsgType: msgType[0],
          Event: event[0],
          Reason: reason[0],
          FailTime: failTime[0]
        }
      } else {
        return {
          ToUserName: toUserName[0],
          FromUserName: fromUserName[0],
          CreateTime: createTime,
          MsgType: msgType[0],
          Event: event[0],
          SuccTime: succTime[0]
        }
      }

      break
  }
}
function encryptMsg (replyMsg, opts) {
  var result = {}
  var options = opts || {}
  result.Encrypt = this.encrypt(replyMsg)
  result.Nonce = options.nonce || parseInt((Math.random() * 100000000000), 10)
  result.TimeStamp = options.timestamp || new Date().getTime()
  result.MsgSignature = this.getSignature(result.TimeStamp, result.Nonce, result.Encrypt)
  return result
}
function getSignature (timestamp, nonce, encrypt) {
  var raw_signature = [token, timestamp, nonce, encrypt].sort().join('')
  var sha1 = crypto.createHash('sha1')
  sha1.update(raw_signature)
  return sha1.digest('hex')
}
// 加密
function encrypt (xmlMsg) {
  this.key = new Buffer('4eFnNBsWJ42PlU4Ur087swKsuIEsn2FduWODKGZo7aO' + '=', 'base64') // toString('binary');
  this.iv = this.key.slice(0, 16)
  var random16 = crypto.pseudoRandomBytes(16)
  var msg = new Buffer(xmlMsg)
  var msgLength = new Buffer(4)
  msgLength.writeUInt32BE(msg.length, 0)
  var corpId = new Buffer(this.appID)
  var raw_msg = Buffer.concat([random16, msgLength, msg, corpId]) // randomString + msgLength + xmlMsg + this.corpID;
// var encoded = PKCS7Encoder(raw_msg);
  var cipher = crypto.createCipheriv('aes-256-cbc', this.key, this.iv)
// cipher.setAutoPadding(false);
  var cipheredMsg = Buffer.concat([cipher.update(/* encoded */ raw_msg), cipher.final()])
  return cipheredMsg.toString('base64')
}
// 解密
function decryptMsg (encrypt, msgSignature, timeStamp, nonce, callback) {
  this.key = new Buffer('4eFnNBsWJ42PlU4Ur087swKsuIEsn2FduWODKGZo7aO' + '=', 'base64') // toString('binary');
  this.iv = this.key.slice(0, 16)

  var aesCipher = crypto.createDecipheriv('aes-256-cbc', this.key, this.iv)
  aesCipher.setAutoPadding(false)
  var decipheredBuff = Buffer.concat([aesCipher.update(encrypt, 'base64'), aesCipher.final()])
  decipheredBuff = this.PKCS7Decoder(decipheredBuff)
  var len_netOrder_corpid = decipheredBuff.slice(16)
  var msg_len = len_netOrder_corpid.slice(0, 4).readUInt32BE(0)
// recoverNetworkBytesOrder(len_netOrder_corpid.slice(0, 4));
  var result = len_netOrder_corpid.slice(4, msg_len + 4).toString()
  var appId = len_netOrder_corpid.slice(msg_len + 4).toString()
  if (appId != this.appID) throw new Error('appId is invalid')

  var infoType = this.getXMLNodeValue('InfoType', result)
  var tmp = infoType.split('[')
  infoType = tmp[2].split(']')

  switch (infoType[0]) {
    case 'component_verify_ticket':
      var componentVerifyTicket = this.getXMLNodeValue('ComponentVerifyTicket', result)
      var tmp = componentVerifyTicket.split('[')
      componentVerifyTicket_tmp = tmp[2].split(']')
      console.log('componentVerifyTicket: ', componentVerifyTicket_tmp[0])
      return {
        componentVerifyTicket: componentVerifyTicket_tmp[0],
        infoType: 'component_verify_ticket'
      }
      break
    case 'updateauthorized':
    case 'authorized':
      var authorizerAppid = this.getXMLNodeValue('AuthorizerAppid', result)
      var tmp_authorizerAppid = authorizerAppid.split('[')
      authorizerAppid = tmp_authorizerAppid[2].split(']')
      console.log('authorizerAppid: ', authorizerAppid[0])

      var authorizationCode = this.getXMLNodeValue('AuthorizationCode', result)
      var tmp = authorizationCode.split('[')
      var authorizationCode_tmp = tmp[2].split(']')
      console.log('authorizationCode: ', authorizationCode_tmp[0])
      return {
        authorizationCode: authorizationCode_tmp[0],
        infoType: 'authorized',
        authorizerAppid: authorizerAppid[0]
      }
      break
    case 'unauthorized':
      console.log('unauthorized')
      return {
        infoType: 'unauthorized'
      }
      break
  }
}
function PKCS7Decoder (buff) {
  var pad = buff[buff.length - 1]
  if (pad < 1 || pad > 32) {
    pad = 0
  }
  return buff.slice(0, buff.length - pad)
}
// 统一返回数据
function jsonWrite (ret, param) {
  if (param.flag) {
    if (typeof ret !== 'undefined') {
      return {
        status: true,
        data: ret,
        msg: param.msg
      }
    } else {
      return {
        status: true,
        data: null,
        msg: param.msg
      }
    }
  } else {
    return {
      status: false,
      data: null,
      msg: param.msg
    }
  }
}
// 解析xml文件
function getXMLNodeValue (node_name, xml) {
  try {
    var tmp = xml.split('<' + node_name + '>')
    var _tmp = tmp[1].split('</' + node_name + '>')
    return _tmp[0]
  } catch (err) {
    console.log(err)
    return '[error]'
  }
}

async function dateFormat (time, type) {
  let t = new Date(time)
  let yy = t.getFullYear()
  let mm = t.getMonth() + 1
  let dd = t.getDate()
  let hh = t.getHours()
  let ss = t.getMinutes()
  let mmm = t.getSeconds()

  if (mm < 10) mm = '0' + mm
  if (dd < 10) dd = '0' + dd
  if (hh < 10) hh = '0' + hh
  if (ss < 10) ss = '0' + ss
  if (mmm < 10) mmm = '0' + mmm

  switch (type) {
    case 0:
      return yy + '-' + mm + '-' + dd + ' ' + hh + ':' + ss + ':' + mmm
    case 1:
      return yy + '-' + mm + '-' + dd
    case 2:
      return yy + '/' + mm + '/' + dd
    case 3:
      return yy + '-' + mm + '-' + dd + ' ' + hh + ':' + ss
    case 4:
      return yy + '.' + mm + '.' + dd
    default:
      return yy + '-' + mm + '-' + dd + ' ' + hh + ':' + ss + ':' + mmm
  }
}
// 发送模版消息
// function sendTemplateMsg (param, callback) {
//   redis.get('miniapp_access_token').then(function (miniapp_access_token) {
// // 存在，获取小程序码
//     console.log('miniapp_access_token: ', miniapp_access_token)

//     if (miniapp_access_token) {
//       param.access_token = miniapp_access_token
//       _this.sendingTemplateMsg(param, callback)
//     } else {
/// / 不存在，获取accessToken
//       _this.getAccessToken(param, callback)
//     }
//   })
// }
// // 马上发送模版消息
// function sendingTemplateMsg (param, callback) {
//   console.log(param)
//   var opts = {
//     url: `https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=${param.access_token}`,
//     method: 'post',
//     body: JSON.stringify(param)
//   }

//   request(opts, function (err, res, body) {
//     var body = JSON.parse(body)
//     console.log(body)
// // token过期，需要重新获取
//     if (body.errcode == 42001 || body.errcode == 40001) {
//       _this.getAccessToken(param, callback)
//     } else {
//       callback(err, null)
//     }
//   })
// }
// // 获取电话号码
// function decryptData (param) {
// // base64 decode
// // console.log(param)
//   var sessionKey = new Buffer(param.session_key, 'base64')
//   encryptedData = new Buffer(param.encryptedData, 'base64')
//   iv = new Buffer(param.iv, 'base64')

//   try {
// // 解密
//     var decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv)
// // 设置自动 padding 为 true，删除填充补位
//     decipher.setAutoPadding(true)
//     var decoded = decipher.update(encryptedData, 'binary', 'utf8')
//     decoded += decipher.final('utf8')

//     decoded = JSON.parse(decoded)

//     console.log(decoded)
//     return (decoded)
//   } catch (err) {
//     console.log(err)
//     throw new Error('Illegal Buffer')
//   }
// }
// 排序
function compareDesc (property) {
  return function (a, b) {
    var value1 = a[property]
    var value2 = b[property]
    return value2 - value1
  }
}

module.exports = {
  getWechatOpenid, jsonWrite, dateFormat, getWexinUserInfo, compareDesc
}
